<template>
    <el-form @submit.prevent :model="model" v-bind="_options" ref="formRef" label-width="110px" label-position="left">
        <el-row :gutter="35">
            <template v-for="(item, index) in fieldList" :key="index">
                <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
                    <!-- 单选框 -->
                    <el-form-item :label="item.label" v-if="item.type === 'radio'" :rules="item.rules"
                        :prop="[item.field]">
                        <el-radio-group v-model="model[item.field]" :disabled="item.disabled">
                            <el-radio :label="val[item.options?.valueKey || 'value']" size="large"
                                v-for="val in item.options?.data" :key="val[item.options?.valueKey || 'value']">
                                {{ val[item.options?.labelkey || 'label'] }}
                            </el-radio>
                        </el-radio-group>
                    </el-form-item>
                    <!-- 复选框 -->
                    <el-form-item :label="item.label" v-else-if="item.type === 'checkbox'" :rules="item.rules"
                        :prop="[item.field]">
                        <el-checkbox-group v-model="model[item.field]" :disabled="item.disabled">
                            <el-checkbox v-for="c in item.options?.data" :key="c[item.options?.valueKey || 'value']"
                                :label="c[item.options?.valueKey || 'value']">{{ c[item.options?.labelkey || 'label']
                                }}</el-checkbox>
                        </el-checkbox-group>
                    </el-form-item>
                    <!-- 下拉框 -->
                    <el-form-item :label="item.label" v-else-if="item.type === 'select'" :rules="item.rules"
                        :prop="[item.field]">
                        <el-select v-model="model[item.field]" :placeholder="item.options?.placeholder || '请选择'"
                            :clearable="item.clearable">
                            <el-option v-for="s in item.options?.data" :key="s[item.options?.valueKey || 'value']"
                                :label="s[item.options?.labelkey || 'label']"
                                :value="s[item.options?.valueKey || 'value']" />
                        </el-select>
                    </el-form-item>

                    <!-- 树形下拉框 -->
                    <el-form-item :label="item.label" v-else-if="item.type === 'treeselect'" :rules="item.rules"
                        :prop="[item.field]">
                        <el-tree-select check-strictly :render-after-expand="true" 
                        class="w100"
                        :default-expand-all="true"
                        v-model="model[item.field]" 
                        :data="item.options?.data"
                        :placeholder="item.options?.placeholder || '请选择'"
                        :clearable="item.clearable">
                            
                        </el-tree-select>
                    </el-form-item>

                    <!-- 级联选择框 -->
                    <el-form-item :label="item.label" v-else-if="item.type === 'cascader'" :rules="item.rules"
                        :prop="[item.field]">
                        <el-cascader 
                        :props="{checkStrictly: true}"
                        :options="item.options?.data"
                        class="w100"
                        :render-after-expand="true" 
                        :default-expand-all="true"
                        v-model="model[item.field]" 
                        :placeholder="item.options?.placeholder || '请选择'"
                        :clearable="item.clearable">
                        <template #default="{ node, data }">
                            <span>{{ data.label }}</span>
                            <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
						</template>
                        </el-cascader>

                    </el-form-item>

                    <!-- 默认输入框 -->
                    <el-form-item :label="item.label" :rules="item.rules" :prop="[item.field]" v-else>
                        <el-input v-model="model[item.field]" :readonly="item.readonly" :type="item.type ?? 'text'"
                            :placeholder="item.placeholder || item.label" :disabled="item.disabled"
                            :showPassword="item.showPassword" :clearable="item.clearable"
                            @keyup.enter="handleKeyUp(item.enterable)" />
                    </el-form-item>
                </el-col>
            </template>
        </el-row>
        <el-form-item>
            <slot name="buttons" :model="model" :formRef="formRef">
                <el-button type="primary" @click="onSubmit(formRef)" v-if="_options.showSubmitButton">{{
                        _options.submitButtonText
                }}</el-button>
                <el-button v-if="_options.showResetButton" type="info" @click="resetForm(formRef)">
                    {{ _options.resetButtonText }}
                </el-button>
                <el-button v-if="_options.showCancelButton" @click="emit('cancel')">
                    {{ _options.cancelButtonText }}
                </el-button>
            </slot>
        </el-form-item>
    </el-form>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'element-plus'
import { ComputedRef, ref, computed , watchEffect } from 'vue'
// 父组件传递的值
interface Props {
    fieldList: Form.FieldItem[]
    model?: Record<string, any>
    options?: Form.Options
}
// 表单的数据
const model = ref<Record<string, any>>({})
const formRef = ref<FormInstance>()
const props = defineProps<Props>()
// 设置option默认值，如果传入自定义的配置则合并option配置项
const _options: ComputedRef<Form.Options> = computed(() => {
    const option = {
        labelPosition: 'right',
        disabled: false,
        showResetButton:false,
        submitButtonText: '提交',
        resetButtonText: '重置',
        cancelButtonText: '取消'
    }
    return Object.assign(option, props?.options)
})
interface EmitEvent {
    (e: 'submit', params: any): void
    (e: 'reset'): void
    (e: 'cancel'): void
}
const emit = defineEmits<EmitEvent>()

// const model = ref<Record<string, any>>({})
// 根据fieldList初始化model， 如果model有传值就用传递的model数据模型，否则就给上面声明的model设置相应的(key,value) [item.field]， item.value是表单的默认值（选填）
props.fieldList.map((item: Form.FieldItem) => {
    // 如果类型为checkbox，默认值需要设置一个空数组
    const value = item.type === 'checkbox' ? [] : ''
    props.model ? (model.value = props.model) : (model.value[item.field] = item.value || value)
})

// 提交按钮
const onSubmit = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.validate((valid) => {
        if (valid) {
            emit('submit', model.value)
        } else {
            return false
        }
    })
}

const validData = async () => {
    if (!formRef) return
    return formRef.value.validate()
}
// 输入框回车事件
const handleKeyUp = (enterable: boolean | undefined) => {
    if (!enterable) return
    onSubmit(formRef.value)
}
// 重置
const resetForm = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.resetFields()
}

// 监听
watchEffect((oninvalidate)=>{
    props.model
    oninvalidate(()=>{})
    props.fieldList.map((item: Form.FieldItem) => {
        const value = item.type === 'checkbox' ? [] : ''
        props.model ? (model.value = props.model) : (model.value[item.field] = item.value || value)
    })
})

defineExpose({
    formRef,
    validData
})
</script>
<style lang="scss" scoped>

</style>
